/*
 * @Author: Yuluo 568055454@qq.com
 * @Date: 2023年06月16日 23:52:05
 * @LastEditors: Yuluo 568055454@qq.com
 * @LastEditTime: 2023年07月16日 03:42:34
 * @FilePath: \Mood-Blog-System\back\util\log4js\index.js
 * @Description:  log4js日志模块，提供日志记录功能，日志记录到文件，日志记录到数据库，日志记录到控制台等功能
 * Copyright (c) 2023 by Yuluo, All Rights Reserved. 
 */

const { configure, getLogger } = require('log4js')
const { getCallerFilePath, mergeArrayObj } = require('../core')
class Logger {
    _type = 'file';
    _etx = '.log';
    _appenders = {};
    _categories = {};

    constructor() {
        this._init();
    }
    /**
     * @description: 初始化 
     * @return {void}
     */
    _init() {
        this._appenders.default = { type: "file", filename: "logs/default.log" };
        this._categories.default = { appenders: ["default"], level: "info" };
    }
    /**
     * @description: 创建日志
     * @param {String} name 已注册的日志名称
     * @param {String} level 日志等级
     * @param {String} type 日志类型
     * @return {void} 函数无返回值
     */
    _createLogger(name, level, type) {
        type = type || this._type;
        if (!name | !level) throw new Error('name and level is required');
        this._appenders[name] = { type: type, filename: `logs/${name}${this._etx}` };
        this._categories[name] = { appenders: [name], level };
        configure({
            appenders: this._appenders,
            categories: this._categories
        })
    }

    /**
     * @description: 获取日志
     * @param {String} name 已注册的日志名称
     * @return {import('log4js').Logger} 返回一个Logger对象, 用于通过name获取日志实例
     */
    _getLogger(name) {
        return getLogger(name);
    }
}

/**
 * @description: 访问日志模板
 * @param {import('koa').Context} ctx  包含request和response等信息的对象
 * @param {object} others 其他需要添加在日志中的信息, 默认为空对象
 * @return {String | object} 返回日志模板字符串/对象
 */
function accessLogTemplate(ctx, others = {}) {
    const log = {
        method: ctx.method,
        url: ctx.url,
        host: ctx.get('host'),
        ip: ctx.get('X-Real-IP') || ctx.get('X-Forwarded-For') || ctx?.ip,
        status: ctx.status,
        authorization: ctx.get('Authorization'),
        userAgent: ctx.get('User-Agent'),
        referrer: ctx.get('Referrer'),
        path: getCallerFilePath(),
    };
    return { ...others, ...log };
}
/**
 * @description: 响应日志模板
 * @param {import('koa').Context} ctx 包含request和response等信息的对象
 * @param {object} others 其他需要添加在日志中的信息 默认为空对象
 * @return {object | String} 返回日志模板字符串/对象 
 */
function responseLogTemplate(ctx, others = {}) {
    const log = {
        method: ctx?.method,
        url: ctx?.url,
        status: ctx?.status,
        body: JSON.stringify(ctx?.body || '{}'),
        path: getCallerFilePath(),
    }

    return { ...others, ...log };
}

function logTemplate(log = []) {
    if (Array.isArray(log)) {
        log.unshift({ path: this.path || getCallerFilePath() })
        log = mergeArrayObj([...log]);
    }
    if (typeof log === 'object') {
        log = Object.assign({ path: this.path || getCallerFilePath() }, log);
    }
    return log;
}

module.exports = new Logger();
module.exports.accessLogTemplate = accessLogTemplate;
module.exports.responseLogTemplate = responseLogTemplate;
module.exports.logTemplate = logTemplate;